#ifndef GY_OBJECT_H
#define GY_OBJECT_H

#include <QObject>
#include <QGraphicsItem>
#include "GY_ControlLibrary_global.h"
#include "./DataAttributes/GY_PropertyInfo.h"

/**
 * @brief The GY_Object class  画板基类，提供公用的方法
 */

/**
 * @brief The GY_ENUM enum  图元标记key
 */
enum GY_ENUM{
    //!对象名称
    ObjectName,
    //!编辑点
    EditPointF,
    //!中心点
    CenterPointF,
    //!对象类型
    ObjectType = 10,
    //!是否复制
    IsCopy = 20,
    //!图元类类型
    ClassType = 30,
};

enum DataType{
    //!默认类型
    PointDefaultType,
    //!父类类型
    PointParentType,
    //!场景类型
    PointSceneType,
};

/**
 * @brief The LineStyle struct 线条样式结构体
 */
struct LineStyle {
    LineStyle() {
        joinMap.insert("miter",Qt::MiterJoin);
        joinMap.insert("joint",Qt::SvgMiterJoin);
        joinMap.insert("round",Qt::RoundJoin);
        capMap.insert("butt",Qt::FlatCap);
        capMap.insert("square",Qt::SquareCap);
        capMap.insert("round",Qt::RoundCap);
    }
    //!宽度
    qreal width;
    //!线条格式
    QString line;
    //!连接样式
    QString join;
    //!笔帽样式
    QString cap;

    QMap<QString,Qt::PenJoinStyle> joinMap;
    QMap<QString,Qt::PenCapStyle> capMap;
};
Q_DECLARE_METATYPE(LineStyle);
/**
 * @brief The GY_Object class
 * 图形对象基类
 */
class GY_CONTROLLIBRARY_EXPORT GY_Object: public QObject
{
    Q_OBJECT
public:
    explicit Q_INVOKABLE GY_Object(const QString &guid,QObject *parent=nullptr);
    ~GY_Object();
    /**
     * @brief isBind 属性是否绑定map
     */
    QMap<QString,bool> isBind;
    /**
     * @brief setConnect 重新关联属性信号和槽
     */
    void setConnect();
    /**
     * @brief copyItem 拷贝图元
     * @param guid 不同id号
     * @return 只有guid不一样的图元
     */
    virtual GY_Object* copyItem(const QString& guid = QString()){
        Q_UNUSED(guid)
        return nullptr;
    }
//    void addProperty(const QString &name);//QString, GY_PropertyInfo
    /**
     * @brief getCenterPointF 获取中心点坐标
     * @return  返回中心点坐标
     */
    QPointF getCenterPointF();
    /**
     * @brief getEditPointF 获取编辑点
     * @return 返回编辑点Map
     */
    QMap<QVariant,QPointF> getEditPointF();
    /**
     * @brief getObjName  获取对象名称
     * @return 返回对象的名称
     */
    QString getObjName() const;
    /**
     * @brief setObjName 设置对象名称
     * @param value 对象名称
     */
    void setObjName(const QString &value);
    /**
     * @brief getGuid  获取GUID
     * @return 返回GUID
     */
    QString getGuid() const;
    /**
     * @brief setGuid 设置GUID
     * @param guid
     */
    void setGuid(const QString& guid);
    /**
     * @brief setUserData 设置用户数据，设定为标记数据，通过该信息判断对象属性及类型,也可以自定义判定数据内容
     * @param id
     * @param val
     */
    void setUserData(const int &id , const QVariant &val);
    QGraphicsItem *getGraphicsItem();
    QVariant getUserData(const int &id);
    /**
     * @brief updateProperty 更新图元属性 , 由具体类实现属性修改
     * @param name 自定义的属性名称
     * @param value 自定义的属性值
     * @param pointType 点类型，2 scene，1 parent, 0 自己判断有无父级更新
     * @return 是否更新成功
     */
    virtual bool updateProperty(const QString &name, const QVariant &value, const DataType &pointType = PointDefaultType);
    /**
     * @brief getProperty 获取图元属性
     * @param name  属性名称
     * @param value 返回属性的值
     * @return 是否获取成功
     */
    virtual bool getProperty(const QString &name ,QVariant &value);
    /**
     * @brief submittingPropertyValues 提交属性值
     * @param value 未筛选属性值
     * @param item 图元对象
     * @return 属性值
     */
    QVariant submittingPropertyValues(const int &updateType,const QVariant &value,const QGraphicsItem *item);
    /**
     * @brief getPropertyMap 获取属性列表
     * @return 属性列表
     */
    QMap<QString,GY_PropertyInfo> getPropertyMap();
    /**
     * @brief getPurObject 获取对象指针
     * @param name 变量名称
     * @param obj 空指针
     * @param childrensMap map容器
     * @return 对象指针
     */
    virtual GY_Object* getPurObject(const QString& purposeObjName, GY_Object* obj, QMap<QString,GY_Object*> childrensMap);
    /**
     * @brief checkVarName 判断变量名称是否存在且合理
     * @param list 变量名称
     * @param childrensMap map容器
     * @return 判断结果
     */
    virtual bool checkVarName(const QStringList& list, QMap<QString,GY_Object*> childrensMap);
    /**
     * @brief getPurposeType 获取目的属性类型
     * @param list 属性名称
     * @param childrensMap map容器
     * @return 属性类型
     */
    virtual PropertyType getPurposeType(const QStringList& list, QMap<QString,GY_Object*> childrensMap);
    /**
     * @brief setRepeatNum 设置RepeatGroup复制个数
     * @param num 复制个数
     */
    void setRepeatNum(const int& num);
    /**
     * @brief getRepeatNum 获取RepeatGroup复制个数
     * @return 复制个数不包括原图
     */
    int getRepeatNum();

protected:
    //!RepeatGroup复制个数
    int m_RepeatNum = -1;
    //!对象图形指针
    QGraphicsItem *m_pItem = nullptr;
    //!更新属性函数指针定义
    typedef bool (GY_Object::*UpdatePropertyFun)(const QString & , const QVariant &);
    //!属性信息Map
    QMap<QString,GY_PropertyInfo> m_PropertyInfoMap;
    //!自定义guid
    int m_MyGuid = 1;
    //!中心点
    QPointF centerPointF=QPointF(0.00001,0);
    /**
     * @brief setCenterPointF 设置中心点
     * @param pointF 中心点坐标
     */
    void setCenterPointF(const QPointF &pointF);
    /**
     * @brief setEditPointF 设置编辑点
     * @param map 编辑点Map
     */
    void setEditPointF(QMap<QVariant,QPointF> &map);
    /**
     * @brief setEditPointF  设置单个编辑点
     * @param key 编辑点名称
     * @param p 编辑点
     */
    void setEditPointF(const QVariant &key , const QPointF &p);
    /**
     * @brief setEditPointF  删除编辑点
     * @param key 编辑点名称
     */
    void deleeteEditPointF(const QVariant &key);/**
     * @brief updateObjectName  更新项目名称
     * @param name 属性名称
     * @param value 项目名称QString
     * @return 返回更新是否成功
     */
    bool updateObjectName(const QString &name, const QVariant &value);
    /**
     * @brief getInheritAttributes 获取最上层属性map
     * @param name 继承笔还是笔刷
     * @param obj 属性对象
     * @return 最上层属性map
     */
    QMap<QString, GY_PropertyInfo> getInheritAttributes(const QString& name, GY_Object *obj);
    /**
     * @brief setpItem 设置对象图形指针m_pItem
     * @param pItem 对象图形指针
     */
    void setpItem(QGraphicsItem *pItem);
private:
    //!编辑点
    QMap<QVariant,QPointF> editPointFMap;
    //!对象名称
//    QString objName;
    //!对象唯一编码
    QString m_Guid;
signals:
    /**
     * @brief updatePropertyEvent 更新属性事件
     * @param pObject 更新属性的对象
     * @param propertyName 属性名称
     * @param propertyValue 属性值
     * @param type 属性类型
     */
    void updatePropertyEvent(const GY_Object* pObject,const QString &propertyName,const QVariant &propertyValue,const PropertyType& type);
    /**
     * @brief copyItemSig 复制品复制信号
     * @param obj 复制品
     */
    void copyItemSig(GY_Object** obj);
    /**
     * @brief itemRectChange 图形大小改变信号
     */
    void itemRectChange();
public slots:
    /**
     * @brief originalVersion 原版复制函数
     * @param obj 复制品
     */
    void originalVersion(GY_Object** obj);
};

#endif // GY_OBJECT_H
